/******************************************************************************
 *  _____     _____
 *  \  __\    \  __\
 *   \ \_\\    \ \_\\
 *    \  __\SS  \  __\roject
 *     \_\       \_\
 *
 * Mateusz Maciąg, Rafał Urbański
 * Komputerowe Systemy Sterowania
 *****************************************************************************/

#ifndef WAVEFORMCONTAINER_H
#define WAVEFORMCONTAINER_H

#include "WaveformBase.h"
#include "SimInterface/ISimulator.h"
#include "SimInterface/IConfigurable.h"

#include <vector>
#include <boost/smart_ptr.hpp>

// Przestrzeń nazw
namespace RafMat
{
namespace SimEngine
{

// Deklaracje zapowiadające
class WaveformContainer;

/** Alias na typ zręcznego wskaźnika na obiekt WaveformContainer */
typedef boost::shared_ptr<WaveformContainer> WaveformContainerSPtr;

/**
    Klasa reprezentuje zbiór sygnałów.

    Klasa ukrywa w sobie wektor wkaźników do sygnałów
    zgodnych z typem WaveformBase. Umożliwia dodawanie
    sygnałów oraz ich usuwanie. Dodatkowo ewaluowana jest
    wartość sumy sygnałów za pomocą metody \c currentValue().
*/
class WaveformContainer : public SimInterface::IConfigurable
{
public:
    /**
        Tworzy nowy kontener na sygnały.
        \param [in] isim Obiekt symulatora-właściciela tej instancji.
    */
    WaveformContainer(SimInterface::ISimulator& isim);

    /**
        Zwraca aktualną wartość sumy sygnałów zawartych w kontenerze.
    */
    double currentValue() const;

    /** Zwraca wszystkie wejścia. */
    const std::vector<WaveformBaseSPtr>& getWaveforms() const { return m_waveforms; }

    /**
        Wstawia nowy sygnał do kontenera.
        Sygnał dopisywany jest do końca listy, co nie ma znaczenia ze
        względu na przemiennośc sumy.
        \param [in] waveform Zręczny wskaźnik na wstawiany generator sygnału.
    */
    void insertWaveform(WaveformBaseSPtr waveform);

    /**
        Usuwa sygnał z kontenera.
        Podanie błędnego wskaźnika nie wpływa na stan obiektu.
        \param [in] Wskaźnik na sygnał, który chcemy usunąć
    */
    void removeWaveform(WaveformBaseSPtr waveform);

    //
    // Implementacja IConfigurable
    //
    /**
        Przypisuje określonemu parametrowi pewną wartość.
        Klasa implementująca ma za zadanie rozróżnić znaczenie parametrów
        oraz zasygnalizować ewentualny błąd użytkownika za pomocą wyjątku std::iconf_error.

        \param [in] param parametr, do którego zapisujemy.
        \param [in] value wartość, którą zapisujemy (w formie łańcucha znaków).
        \throws std::iconf_error - gdy parametr lub wartość nie zgadza się
        syntaktycznie z daną implementacją.
    */
    virtual bool setParameter(const std::string& p, const std::string&) throw(std::logic_error)
    { throw SimInterface::iconf_error::unrecognizedParam(*this, p); }

    /**
        Odczytuje określony parametr.
        Klasa implementująca ma za zadanie rozróżnić czego od niej się chce
        oraz zasygnalizować ewentualny błąd parametru.

        \param [in] param parametr, który chcemy odczytać.
        \return Wartość odpowiadająca parametrowi w formie łańcucha znaków.
        \throws std::iconf_error - gdy parametr nie zgadza się
        syntaktycznie z daną implementacją.
    */
    virtual std::string getParameter(const std::string& p) const throw(std::logic_error)
    { throw SimInterface::iconf_error::unrecognizedParam(*this, p); }

    /**
        Wysyła stan obiektu do strumienia.

        \param [in/out] o strumień docelowy.
        \return Strumień przekazany funkcji.
    */
    virtual SimFile::ConfigWriter& dumpParameters(SimFile::ConfigWriter& o) const;

private:
    SimInterface::ISimulator &m_simulator;      ///< Obiekt symulatora zarządzającego tą instancją.

    std::vector<WaveformBaseSPtr> m_waveforms;  ///< Wektor sygnałów.
};

}
}

#endif // WAVEFORMCONTAINER_H
